package com.cinema.dao;

import com.cinema.entity.*;
import com.cinema.util.DBUtil;

import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 场次数据访问对象
 */
public class ShowtimeDAO {

    /**
     * 根据电影ID获取场次列表
     */
    public List<Showtime> findByMovieId(Integer movieId) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<Showtime> showtimes = new ArrayList<>();

        try {
            conn = DBUtil.getConnection();
            String sql = "SELECT s.*, m.title as movie_title, m.poster_url, m.duration, " +
                        "c.name as cinema_name, c.address as cinema_address, h.name as hall_name " +
                        "FROM showtimes s " +
                        "LEFT JOIN movies m ON s.movie_id = m.id " +
                        "LEFT JOIN cinemas c ON s.cinema_id = c.id " +
                        "LEFT JOIN halls h ON s.hall_id = h.id " +
                        "WHERE s.movie_id = ? AND s.status = 'SELLING' " +
                        "AND (s.show_date > CURDATE() OR " +
                        "(s.show_date = CURDATE() AND s.show_time > CURTIME())) " +
                        "ORDER BY s.show_date, s.show_time";

            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, movieId);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                Showtime showtime = mapResultSetToShowtime(rs);

                // 设置关联对象
                Movie movie = new Movie();
                movie.setId(rs.getInt("movie_id"));
                movie.setTitle(rs.getString("movie_title"));
                movie.setPosterUrl(rs.getString("poster_url"));
                movie.setDuration(rs.getInt("duration"));
                showtime.setMovie(movie);

                Cinema cinema = new Cinema();
                cinema.setId(rs.getInt("cinema_id"));
                cinema.setName(rs.getString("cinema_name"));
                cinema.setAddress(rs.getString("cinema_address"));
                showtime.setCinema(cinema);

                Hall hall = new Hall();
                hall.setId(rs.getInt("hall_id"));
                hall.setName(rs.getString("hall_name"));
                showtime.setHall(hall);

                showtimes.add(showtime);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt, rs);
        }

        return showtimes;
    }

    /**
     * 根据ID获取场次详情
     */
    public Showtime findById(Integer id) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        Showtime showtime = null;

        try {
            conn = DBUtil.getConnection();
            String sql = "SELECT s.*, m.title as movie_title, m.duration, m.poster_url, " +
                        "c.name as cinema_name, c.address as cinema_address, " +
                        "h.name as hall_name, h.total_seats " +
                        "FROM showtimes s " +
                        "LEFT JOIN movies m ON s.movie_id = m.id " +
                        "LEFT JOIN cinemas c ON s.cinema_id = c.id " +
                        "LEFT JOIN halls h ON s.hall_id = h.id " +
                        "WHERE s.id = ?";

            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);
            rs = pstmt.executeQuery();

            if (rs.next()) {
                showtime = mapResultSetToShowtime(rs);

                // 设置关联对象
                Movie movie = new Movie();
                movie.setId(rs.getInt("movie_id"));
                movie.setTitle(rs.getString("movie_title"));
                movie.setDuration(rs.getInt("duration"));
                movie.setPosterUrl(rs.getString("poster_url"));
                showtime.setMovie(movie);

                Cinema cinema = new Cinema();
                cinema.setId(rs.getInt("cinema_id"));
                cinema.setName(rs.getString("cinema_name"));
                cinema.setAddress(rs.getString("cinema_address"));
                showtime.setCinema(cinema);

                Hall hall = new Hall();
                hall.setId(rs.getInt("hall_id"));
                hall.setName(rs.getString("hall_name"));
                hall.setTotalSeats(rs.getInt("total_seats"));
                showtime.setHall(hall);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt, rs);
        }

        return showtime;
    }



    /**
     * 获取所有场次列表（管理员用）
     */
    public List<Showtime> findAll() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        List<Showtime> showtimes = new ArrayList<>();

        try {
            conn = DBUtil.getConnection();
            String sql = "SELECT s.*, m.title as movie_title, m.poster_url, m.duration, " +
                        "c.name as cinema_name, c.address as cinema_address, h.name as hall_name " +
                        "FROM showtimes s " +
                        "LEFT JOIN movies m ON s.movie_id = m.id " +
                        "LEFT JOIN cinemas c ON s.cinema_id = c.id " +
                        "LEFT JOIN halls h ON s.hall_id = h.id " +
                        "ORDER BY s.show_date DESC, s.show_time DESC";

            pstmt = conn.prepareStatement(sql);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                Showtime showtime = mapResultSetToShowtime(rs);

                // 设置关联对象
                Movie movie = new Movie();
                movie.setId(rs.getInt("movie_id"));
                movie.setTitle(rs.getString("movie_title"));
                movie.setPosterUrl(rs.getString("poster_url"));
                movie.setDuration(rs.getInt("duration"));
                showtime.setMovie(movie);

                Cinema cinema = new Cinema();
                cinema.setId(rs.getInt("cinema_id"));
                cinema.setName(rs.getString("cinema_name"));
                cinema.setAddress(rs.getString("cinema_address"));
                showtime.setCinema(cinema);

                Hall hall = new Hall();
                hall.setId(rs.getInt("hall_id"));
                hall.setName(rs.getString("hall_name"));
                showtime.setHall(hall);

                showtimes.add(showtime);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt, rs);
        }

        return showtimes;
    }

    /**
     * 添加场次
     */
    public boolean addShowtime(Showtime showtime) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        boolean success = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "INSERT INTO showtimes (movie_id, cinema_id, hall_id, show_date, show_time, " +
                        "price, available_seats, total_seats, presale_start, booking_end, status) " +
                        "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, showtime.getMovieId());
            pstmt.setInt(2, showtime.getCinemaId());
            pstmt.setInt(3, showtime.getHallId());
            pstmt.setDate(4, new java.sql.Date(showtime.getShowDate().getTime()));
            pstmt.setTime(5, new java.sql.Time(showtime.getShowTime().getTime()));
            pstmt.setBigDecimal(6, showtime.getPrice());
            pstmt.setInt(7, showtime.getAvailableSeats());
            pstmt.setInt(8, showtime.getTotalSeats());
            pstmt.setTimestamp(9, showtime.getPresaleStart() != null ?
                new java.sql.Timestamp(showtime.getPresaleStart().getTime()) : null);
            pstmt.setTimestamp(10, showtime.getBookingEnd() != null ?
                new java.sql.Timestamp(showtime.getBookingEnd().getTime()) : null);
            pstmt.setString(11, showtime.getStatus());

            int rows = pstmt.executeUpdate();
            success = rows > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt);
        }

        return success;
    }

    /**
     * 更新场次
     */
    public boolean updateShowtime(Showtime showtime) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        boolean success = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "UPDATE showtimes SET movie_id = ?, cinema_id = ?, hall_id = ?, " +
                        "show_date = ?, show_time = ?, price = ?, available_seats = ?, " +
                        "total_seats = ?, presale_start = ?, booking_end = ?, status = ? " +
                        "WHERE id = ?";

            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, showtime.getMovieId());
            pstmt.setInt(2, showtime.getCinemaId());
            pstmt.setInt(3, showtime.getHallId());
            pstmt.setDate(4, new java.sql.Date(showtime.getShowDate().getTime()));
            pstmt.setTime(5, new java.sql.Time(showtime.getShowTime().getTime()));
            pstmt.setBigDecimal(6, showtime.getPrice());
            pstmt.setInt(7, showtime.getAvailableSeats());
            pstmt.setInt(8, showtime.getTotalSeats());
            pstmt.setTimestamp(9, showtime.getPresaleStart() != null ?
                new java.sql.Timestamp(showtime.getPresaleStart().getTime()) : null);
            pstmt.setTimestamp(10, showtime.getBookingEnd() != null ?
                new java.sql.Timestamp(showtime.getBookingEnd().getTime()) : null);
            pstmt.setString(11, showtime.getStatus());
            pstmt.setInt(12, showtime.getId());

            int rows = pstmt.executeUpdate();
            success = rows > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt);
        }

        return success;
    }

    /**
     * 删除场次
     */
    public boolean deleteShowtime(Integer id) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        boolean success = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "DELETE FROM showtimes WHERE id = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, id);

            int rows = pstmt.executeUpdate();
            success = rows > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt);
        }

        return success;
    }

    /**
     * 检查场次是否可以预订
     */
    public boolean canBook(Integer showtimeId) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        boolean canBook = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "SELECT available_seats, presale_start, booking_end, status " +
                        "FROM showtimes WHERE id = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, showtimeId);
            rs = pstmt.executeQuery();

            if (rs.next()) {
                int availableSeats = rs.getInt("available_seats");
                Timestamp presaleStart = rs.getTimestamp("presale_start");
                Timestamp bookingEnd = rs.getTimestamp("booking_end");
                String status = rs.getString("status");

                Date now = new Date(System.currentTimeMillis());

                // 添加详细的调试信息
                System.out.println("=== 场次预订检查 ===");
                System.out.println("场次ID: " + showtimeId);
                System.out.println("可用座位数: " + availableSeats);
                System.out.println("状态: " + status);
                System.out.println("预售开始时间: " + presaleStart);
                System.out.println("预订结束时间: " + bookingEnd);
                System.out.println("当前时间: " + now);

                // 简化预订条件，主要检查座位数和状态
                boolean hasSeats = availableSeats > 0;
                boolean isSellingStatus = "SELLING".equals(status);
                boolean presaleOk = (presaleStart == null || now.after(presaleStart));
                boolean bookingOk = (bookingEnd == null || now.before(bookingEnd));

                System.out.println("座位检查: " + hasSeats);
                System.out.println("状态检查: " + isSellingStatus);
                System.out.println("预售时间检查: " + presaleOk);
                System.out.println("预订时间检查: " + bookingOk);

                canBook = hasSeats && isSellingStatus && presaleOk && bookingOk;

                System.out.println("最终结果: " + canBook);
                System.out.println("==================");
            } else {
                System.out.println("场次ID " + showtimeId + " 不存在");
            }
        } catch (SQLException e) {
            System.err.println("检查场次预订状态时发生错误: " + e.getMessage());
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt, rs);
        }

        return canBook;
    }

    /**
     * 增加可用座位数（退票/取消订单时使用）
     */
    public boolean increaseAvailableSeats(Integer showtimeId, Integer seatCount) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        boolean success = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "UPDATE showtimes SET available_seats = available_seats + ? WHERE id = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, seatCount);
            pstmt.setInt(2, showtimeId);

            int rows = pstmt.executeUpdate();
            success = rows > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt);
        }

        return success;
    }

    /**
     * 减少可用座位数（订票/改票时使用）
     */
    public boolean decreaseAvailableSeats(Integer showtimeId, Integer seatCount) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        boolean success = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "UPDATE showtimes SET available_seats = available_seats - ? WHERE id = ? AND available_seats >= ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, seatCount);
            pstmt.setInt(2, showtimeId);
            pstmt.setInt(3, seatCount);

            int rows = pstmt.executeUpdate();
            success = rows > 0;
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt);
        }

        return success;
    }

    /**
     * 简化版本的预订检查（用于快速修复）
     */
    public boolean canBookSimple(Integer showtimeId) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        boolean canBook = false;

        try {
            conn = DBUtil.getConnection();
            String sql = "SELECT available_seats, status FROM showtimes WHERE id = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setInt(1, showtimeId);
            rs = pstmt.executeQuery();

            if (rs.next()) {
                int availableSeats = rs.getInt("available_seats");
                String status = rs.getString("status");

                // 简化检查：只检查座位数和状态
                canBook = availableSeats > 0 && "SELLING".equals(status);

                System.out.println("简化预订检查 - 场次ID: " + showtimeId +
                                 ", 可用座位: " + availableSeats +
                                 ", 状态: " + status +
                                 ", 结果: " + canBook);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            DBUtil.close(conn, pstmt, rs);
        }

        return canBook;
    }

    /**
     * 将ResultSet映射为Showtime对象
     */
    private Showtime mapResultSetToShowtime(ResultSet rs) throws SQLException {
        Showtime showtime = new Showtime();
        showtime.setId(rs.getInt("id"));
        showtime.setMovieId(rs.getInt("movie_id"));
        showtime.setCinemaId(rs.getInt("cinema_id"));
        showtime.setHallId(rs.getInt("hall_id"));
        showtime.setShowDate(rs.getDate("show_date"));
        showtime.setShowTime(rs.getTimestamp("show_time"));
        showtime.setPrice(rs.getBigDecimal("price"));
        showtime.setAvailableSeats(rs.getInt("available_seats"));
        showtime.setTotalSeats(rs.getInt("total_seats"));
        showtime.setPresaleStart(rs.getTimestamp("presale_start"));
        showtime.setBookingEnd(rs.getTimestamp("booking_end"));
        showtime.setStatus(rs.getString("status"));
        showtime.setCreatedAt(rs.getTimestamp("created_at"));
        return showtime;
    }
}
